﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SMS.Entities.BaseClasses;
using SMS.Model;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Collections;

namespace SMS.ViewModel
{
    public class ViewModel_ResetPassword : BaseNotify, INotifyDataErrorInfo
    {
        /// <summary>
        /// AuthenticationModel Object
        /// </summary>
        AuthenticationModel authObject;
        /// <summary>
        /// 
        /// </summary>
        public ViewModel_ResetPassword()
        {
            IntializeModel();
            OkButtonCommand = new Common.Silverlight.DelegateCommand(ok_Click, null);
            CancelCommand = new Common.Silverlight.DelegateCommand(Cancel, null);
            this.errors = new Dictionary<string, List<string>>();
        }

        private void IntializeModel()
        {
            authObject = new AuthenticationModel();
        }

        void ok_Click(object sender)
        {
            #region "For Validations"
            var allErrors = new Dictionary<string, List<string>>();

            foreach (var err in errors)
            {
                allErrors.Add(err.Key, err.Value);
            }
            foreach (var prvError in allErrors)
            {
                RemoveErrorFromProperty(prvError.Key, null, true);
            }

            errors.Clear();

            this.ValidationResults = new ObservableCollection<ValidationResult>();

            bool isValid = Validator.TryValidateObject(this, new ValidationContext(this, null, null), this.ValidationResults, true);
            if (!isValid)
            {

                foreach (ValidationResult vr in ValidationResults)
                {
                    string[] msgs = { vr.ErrorMessage };
                    AddErrorToProperty(((string[])(vr.MemberNames))[0], msgs, true);
                }
                return;
            }
            #endregion

            if (NewPassword != ConfirmNewPassword)
            {
                ErrorMessage= "Password must be same";
                return;
            }
            authObject.OnResetPasswordCompleted += new Action<int>(authObject_OnResetPasswordCompleted);
            authObject.ResetPassword(App.LoggedinUserName, CurrentPassword, NewPassword);            
        }

        void authObject_OnResetPasswordCompleted(int obj)
        {
            if (obj > 0)
                UserMessage= "Your Password have been changed successfully.";
            else
                ErrorMessage= "Error Occured!!";
        }

        private void Cancel(object param)
        {
            App.GoBack();
        }

        #region Properties

        private string  _currentPassword;
        [Required(ErrorMessage="Current Password is required")]
        public string  CurrentPassword
        {
            get { return _currentPassword; }
            set { _currentPassword = value; OnPropertyChanged("CurrentPassword"); }
        }

        private string _newPassword;
        [Required(ErrorMessage = "Current Password is required")]
        public string NewPassword
        {
            get { return _newPassword; }
            set { _newPassword = value; OnPropertyChanged("NewPassword"); }
        }


        private string _confirmNewPassword;
        [Required(ErrorMessage = "Current Password is required")]
        public string ConfirmNewPassword
        {
            get { return _confirmNewPassword; }
            set { _confirmNewPassword = value; OnPropertyChanged("ConfirmNewPassword"); }
        }
        

        #endregion

        public ICommand OkButtonCommand { get; set; }
        public ICommand CancelCommand { get; set; }

        #region "INotifyDataErrorInfo members implementation"

        ObservableCollection<ValidationResult> validationResults;
        public ObservableCollection<ValidationResult> ValidationResults
        {
            get
            {
                return this.validationResults;
            }
            set
            {
                this.validationResults = value;
                this.OnPropertyChanged("ValidationResults");
            }
        }

        private readonly Dictionary<string, List<string>> errors;

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        public IEnumerable GetErrors(string propertyName)
        {
            if ((!this.errors.ContainsKey(propertyName)) || string.IsNullOrEmpty(propertyName)) return this.errors;

            return this.errors[propertyName];
        }

        public bool HasErrors
        {
            get { return this.errors.Count > 0; }
        }

        public void Clear()
        {
            this.errors.Clear();
        }

        public void RemoveErrorFromProperty(string propertyName, string errorMessage = null, bool notifyErrorschanged = false)
        {
            if (!this.errors.ContainsKey(propertyName)) return;

            this.RemoveErrorFromPropertyIfErrorAlreadyExist(propertyName);

            if (notifyErrorschanged) this.NotifyErrorsChanged(propertyName);
        }

        private void RemoveErrorFromPropertyIfErrorAlreadyExist(string propertyName)
        {
            if (!this.errors.ContainsKey(propertyName)) return;

            this.errors[propertyName].Clear();
            if (this.errors[propertyName].Count == 0) this.errors.Remove(propertyName);
        }

        private void NotifyErrorsChanged(string propertyName)
        {
            if (this.ErrorsChanged != null)
                this.ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
        }

        public void AddErrorToProperty(string propertyName, string[] errorMessage, bool notifyErrorschanged = false)
        {
            this.RemoveErrorFromPropertyIfErrorAlreadyExist(propertyName);

            if (!this.errors.ContainsKey(propertyName)) this.errors.Add(propertyName, new List<string>());

            foreach (var message in errorMessage)
            {
                this.errors[propertyName].Add(message);
            }

            if (notifyErrorschanged) this.NotifyErrorsChanged(propertyName);
        }
        #endregion
    }
}
